package com.yunxin.customui.bean.table;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.yunxin.customui.bean.UIComponent;
import com.yunxin.customui.bean.table.datatable.TableBusinessConfig;
import com.yunxin.customui.bean.table.datatable.TableDataTemplate;
import com.yunxin.customui.service.builder.table.DefaultBuilder;
import com.yunxin.customui.bean.table.sqltable.TableSqlColumn;
import com.yunxin.customui.myinterface.table.FormulaData;
import com.yunxin.customui.myinterface.table.ITableBuilder;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * 表的bean
 * 功能描述:
 * 前台表格展示bean
 * 内部应该有bean的所有属性，不仅仅有数据属性，也有表格自身（行啊列啊样式啊 合并啊 单元格处理策略啊等等）的属性
 * date 2021/8/2 14:18
 *
 * @author cc
 * @version 1.0
 * @date 2021/08/26
 */
@Getter
@Setter
public class TableBean extends UIComponent implements Serializable{

    /**
     * 表id
     */
    private Integer tableId;

    /**
     * 类型
     */
    private static final String TYPE = "table";

    /**
     * 事件处理程序
     */
    private String eventHandler;

    /**
     * 配置
     */
    @JsonIgnore
    private TableBusinessConfig config;

    /**
     * 表生成器
     */
    @JsonIgnore
    ITableBuilder tableBuilder;

    /**
     * 有参构造，传入表格配置
     */
    public TableBean(TableBusinessConfig tableDataConfig) {
        super(tableDataConfig.getComponentType(),tableDataConfig.getComponentId());
        initBuilder(tableDataConfig);
        initAttr(tableDataConfig);
    }
    //这个方法临时用，之后会删除
    public TableBean() {
        super("",-1);
    }


    /**
     * 构建表格
     *
     * @param data 数据
     */
    public TableBean build(Object data){
        tableBuilder.buildTable(this,config,data);
        return this;
    }

    /**
     * 初始化建设器
     *
     */
    private void initBuilder(TableBusinessConfig tableDataConfig){
        tableBuilder = new DefaultBuilder();
    }

    /**
     * 初始化表
     *
     * @param tableDataConfig v表配置bean
     */
    private void initAttr(TableBusinessConfig tableDataConfig){
        this.eventHandler = tableDataConfig.getEventHandler();
        this.config = tableDataConfig;
    }

    /**
     * 表头
     */
    @Getter@Setter
    LinkedList<TrBean> thBeans = new LinkedList<>();
    /**
     * 前台展示的所有行集合
     */
    @Getter@Setter
    LinkedList<TrBean> trBeans = new LinkedList<>();

    /**
     * 这列用来对列数据，进行合计，平均值等操作计算
     */
    LinkedList<TrBean> specialRow = new LinkedList<>();
    /**
     * 额外的列  序号 时间等
     */
    LinkedList<String> extraColumns = new LinkedList<>();

    /**
     * 管理列的col属性
     * 比如 第一列 col 1  第二列 col 2   第三列 col 3 则该属性 = [1,2,3]
     * 此时 新增了一列 第四列插入到了第一和第二列中间，则 该属性= [1,4,2,3]
     * 该属性为了防止新增列导致的顺序取col时发生乱序
     */
    LinkedList<Integer> colOrder = new LinkedList<>();

    /**
     * 排序函数，生成表格时候，如果这个属性有值，则会按照该函数结果顺序建表
     */
    private Function<List<String>, List<String>> orderKeyFun;

    /**
     * id和列号的映射  ，目前也就是key : businessId  value:  col（列号）
     */
    Map<String,Integer> idColMapping = new HashMap<>();


    /**
     * 获取列号， 根据businessId
     *
     * @param businessId 业务标识
     * @return 数据所在列号
     */
    public Integer getColByBusinessId(String businessId){
        return idColMapping.get(businessId);
    }

    /**
     * 添加列
     *
     * @param tableDataTemplate   列配置
     * @param list     列表
     * @param function 函数  得到第二个集合参数的函数 作为tdBean的Value
     * @param index    指数
     */
    public <T> void addCol(TableDataTemplate tableDataTemplate, List<T> list, Function<T, String> function, int index) {
        //通过id找到对应列
        TdBean thBean = new TdBean();
        thBean.setValue(tableDataTemplate.getFieldDesc());
        int col = colOrder.stream().distinct().max(Integer::compareTo).orElse(0) + 1;
        thBeans.getLast().getTdBeans().add(index, thBean);
        for (int i = 0; i < trBeans.size(); i++) {
            TdBean tdBean = new TdBean();
            tdBean.setData(tableDataTemplate,String.valueOf(function.apply(list.get(i))));
            tdBean.col=col;
            idColMapping.putIfAbsent(tableDataTemplate.getBusinessId(), col);
            tdBean.row=(i + 1);
            trBeans.get(i).getTdBeans().add(index, tdBean);
        }
        colOrder.add(index, colOrder.size() + 1);
    }


    /**
     * 根据行号获取具体的某行数据
     *
     * @return
     */
    public LinkedList<TdBean> getRow(int rowNum) {
        LinkedList<TdBean> result = new LinkedList<>();
        for (TrBean trBean : trBeans) {
            for (TdBean tdBean : trBean.getTdBeans()) {
                if (tdBean.row == rowNum) {
                    result.add(tdBean);
                    continue;
                }
            }
        }
        return result;
    }

    /**
     * 根据列号选择某列数据
     *
     * @return
     */
    public LinkedList<TdBean> getCol(int colNum) {
        LinkedList<TdBean> result = new LinkedList<>();
        for (TrBean trBean : trBeans) {
            for (TdBean tdBean : trBean.getTdBeans()) {
                if (tdBean.col == colNum) {
                    result.add(tdBean);
                    break;
                }
            }
        }
        return result;
    }
    public List<FormulaData> getColFormulaData(int colNum) {
        List<FormulaData> result = new LinkedList<>();
        for (TrBean trBean : trBeans) {
            for (TdBean tdBean : trBean.getTdBeans()) {
                if (tdBean.col == colNum) {
                    result.add(tdBean);
                    break;
                }
            }
        }
        return result;
    }


    /**
     * 设置排序
     *
     * @param orderKey 排序函数
     */
    public void setOrderFun(Function<List<String>, List<String>> orderKey) {
        this.orderKeyFun = orderKey;
    }


    @Override
    public Integer getComponentId() {
        return this.tableId;
    }


    /**
     * 表头显示列
     */
    List<TableSqlColumn> columns;

}
